import argparse
import html
import os
import json
import copy
import re
import util_themoviedb
import searchinc
import constant


def _plugin_run():
    parser = argparse.ArgumentParser()
    parser.add_argument("--input", type=str, required=True, help='json string')
    parser.add_argument("--lang", type=str, required=True, default=None, help='enu|cht|...')
    parser.add_argument("--type", type=str, required=True, default=None, help='movie|tvshow|...')
    parser.add_argument("--limit", type=int, default=1, help='result count')
    parser.add_argument("--allowguess", type=bool, default=True)

    # unknownPrm is useless, just for prevent error when unknow param inside
    args, unknownPrm = parser.parse_known_args()

    argv_input = json.loads(args.input)
    argv_lang = args.lang
    argv_type = args.type
    argv_limit = args.limit

    cookie_path = searchinc.create_cookie_file()

    result = None
    success = True
    error_code = 0
    try:
        result = _process(argv_input, argv_lang, argv_type, argv_limit)

    except SystemExit as query_e:
        error_code = constant.ERROR_PLUGIN_QUERY_FAIL
        success = False

    except Exception as e:
        error_code = constant.ERROR_PLUGIN_PARSE_RESULT_FAIL
        success = False

    searchinc.delete_cookie_file(cookie_path)
    _process_output(success, error_code, result)


def _process(input_obj, lang, media_type, limit):
    title = input_obj['title']
    year = _get_year(input_obj)

    season = input_obj['season'] if 'season' in input_obj else 0
    episode = input_obj['episode'] if 'episode' in input_obj else None

    query_data = util_themoviedb.search_media(title, lang, limit, media_type, year)

    if len(query_data) < 1:
        return []
    return _get_metadata(query_data, lang, media_type, season, episode, limit)


def _get_year(input_obj):
    year = 0

    if 'original_available' in input_obj:
        year = searchinc.parse_year(input_obj['original_available'])

    if 'extra' in input_obj:
        extraItem = input_obj['extra']
        if 'tvshow' in extraItem and 'original_available' in extraItem['tvshow']:
            year = searchinc.parse_year(extraItem['tvshow']['original_available'])
    return year


def _get_metadata(query_data, lang, media_type, season, episode, limit):
    result = []
    for item in query_data:
        if media_type == 'movie':
            media_data = util_themoviedb.get_movie_detail_data(item['id'], item['lang'], constant.DEFAULT_EXPIRED_TIME)
        elif media_type == 'tvshow' or media_type == 'tvshow_episode':
            media_data = util_themoviedb.get_movie_detail_data(item['id'], item['lang'], constant.DEFAULT_EXPIRED_TIME)
        else:
            return []

        if not media_data:
            continue

        mData = _parse_movie_info(media_data)
        if media_type == 'movie':
            result.append(mData)

        elif media_type == 'tvshow':
            result.append(_parse_tvshow_info(mData))

        elif media_type == 'tvshow_episode':
            episode_data = util_themoviedb.get_tv_episode_detail_data(item['id'], lang, season, episode)
            result.extend(_parse_episodes_info(mData, episode_data, season, episode))

        if limit <= len(result):
            result = result[:limit]
            break

    return result


def _parse_movie_info(movie_data):
    data = copy.deepcopy(constant.MOVIE_DATA_TEMPLATE)
    movie_data = re.sub(r'\n', "", movie_data)
    matchObject = re.search(r'<script type="application/ld\+json">(\{.+?})</script>', movie_data)
    if matchObject:
        jsonobject = json.loads(matchObject.group(1))
        data['title'] = jsonobject['name']
        data['original_available'] = jsonobject['datePublished']
        data['tagline'] = ''
        data['summary'] = jsonobject['description']
        data['certificate'] = ''
        data['genre'] = _parse_genre(jsonobject)
        if '情色' in data['genre']:
            data['certificate'] = 'Q' + data['certificate']
        if '犯罪' in data['genre']:
            data['certificate'] = 'F' + data['certificate']
        if '惊悚' in data['genre']:
            data['certificate'] = 'J' + data['certificate']
        if '恐怖' in data['genre']:
            data['certificate'] = 'K' + data['certificate']
        actor, director, writer = _get_cast_info(jsonobject)
        data['actor'] = actor
        data['director'] = director
        data['writer'] = writer

        if jsonobject['aggregateRating']:
            data = _set_data_value(data, ['extra', constant.PLUGINID, 'rating', constant.PLUGINID],
                                   jsonobject['aggregateRating']['ratingValue'])

        if jsonobject['image']:
            data = _set_data_value(data, ['extra', constant.PLUGINID, 'poster'], [
                jsonobject['image']])

        if jsonobject['image']:
            data = _set_data_value(data, ['extra', constant.PLUGINID, 'backdrop'], [
                jsonobject['image']])
    return data


def _parse_tvshow_info(tv_data):
    data = copy.deepcopy(constant.TVSHOW_DATA_TEMPLATE)

    data['title'] = tv_data['title']
    data['original_available'] = tv_data['original_available']
    data['summary'] = tv_data['summary']

    if tv_data['extra']:
        data['extra'] = tv_data['extra']
    return data


def _parse_episodes_info(tv_data, episode_data, season, episode):
    parse_info_result = [_parse_episode_info(tv_data, episode_data, season, episode)]

    return parse_info_result


def _parse_episode_info(tv_data, episode_data, season, episode):
    data = copy.deepcopy(constant.TVSHOW_EPISODE_DATA_TEMPLATE)

    data['title'] = tv_data['title']
    data['season'] = season
    data['episode'] = episode

    tvshow_data = _parse_tvshow_info(tv_data)
    data = _set_data_value(data, ['extra', constant.PLUGINID, 'tvshow'], tvshow_data)

    data['original_available'] = tv_data['original_available']
    data['certificate'] = tv_data['certificate']
    data['genre'] = tv_data['genre']
    data['actor'] = tv_data['actor']
    data['director'] = tv_data['director']
    data['writer'] = tv_data['writer']
    data['tagline'] = tv_data['tagline']
    data['summary'] = tv_data['summary']
    if tv_data['extra'][constant.PLUGINID]['rating']:
        data = _set_data_value(data, ['extra', constant.PLUGINID, 'rating'],
                               tv_data['extra'][constant.PLUGINID]['rating'])
    if tv_data['extra'][constant.PLUGINID]['poster']:
        data = _set_data_value(data, ['extra', constant.PLUGINID, 'poster'],
                               tv_data['extra'][constant.PLUGINID]['poster'])
    # if episode_data:
    #     episode_data = re.sub(r'\s', "", episode_data)
    #     matchObject = re.search(r'<scripttype="application/ld\+json">(\{.+?})</script>', episode_data)
    #     if matchObject:
    #         data['tagline'] = matchObject.group(1)
    #         data['summary'] = matchObject.group(2)
    return data


def _set_data_value(data, key_list, value):
    if not value:
        return data

    now_data = data
    for attr in key_list[:-1]:
        if attr not in now_data:
            now_data[attr] = {}
        now_data = now_data[attr]

    now_data[key_list[-1]] = value
    return data


def _get_cast_info(cast_data):
    actor = []
    director = []
    writer = []

    if 'actor' in cast_data:
        for item in cast_data['actor']:
            if item['name'] not in actor:
                actor.append(item['name'])

    if 'author' in cast_data:
        for item in cast_data['author']:
            if item['name'] not in writer:
                writer.append(item['name'])

    if 'director' in cast_data:
        for item in cast_data['director']:
            if item['name'] not in director:
                director.append(item['name'])
    return actor, director, writer


def _parse_genre(media_data):
    genre = []
    for item in media_data['genre']:
        if item not in genre:
            genre.append(item)
    return genre


def _process_output(success, error_code, datas):
    result_obj = {}
    if success:
        result_obj = {'success': True, 'result': datas}
    else:
        result_obj = {'success': False, 'error_code': error_code}

    json_string = json.dumps(result_obj, ensure_ascii=False, separators=(',', ':'))
    json_string = html.unescape(json_string)
    print(json_string)


if __name__ == "__main__":
    _plugin_run()
